// 6.5.3 调试帮助
/**
 * C++程序员有时会用到一种类似于头文件保护（参见2.6.3节，第67页）的技术，以便有选择地执行调试代码。
 * 基本思想是，程序可以包含一些用于调试的代码，但是这些代码只在开发程序时使用。
 * 当应用程序编写完成准备发布时，要先屏蔽掉调试代码。
 * 这种方法用到两项预处理功能：assert和NDEBUG
 */
#include <iostream>
#include <initializer_list>
#include <iterator>
#include <vector>
#include <cassert> // assert宏定义在cassert头文件中
using std::begin, std::end;
using std::cin, std::cout, std::endl;
using std::initializer_list;
using std::string;
using std::vector;
using std::cerr,std::clog;

// assert是一种预处理宏（preprocessor marco）。
/**
 * 所谓预处理宏其实是一个预处理变量，它的行为有点类似于内联函数。assert宏使用一个表达式作为它的条件
 * assert(expr);
 * 首先对expr求值，如果表达式为假（即0），assert输出信息并终止程序的执行。如果表达式为真（即非0），assert什么也不做
 * assert宏定义在cassert头文件中。
 * 如我们所知，预处理名字由预处理器而非编译器管理（参见2.3.2节，第49页）
 * 因此我们可以直接使用预处理名字而无须提供using声明。
 * 也就是说，我们应该使用assert而不是std：：assert，也不需要为assert提供using声明。
 * 
 * assert宏常用于检查“不能发生”的条件。
 * 例如，一个对输入文本进行操作的程序可能要求所有给定单词的长度都大于某个阈值。
 */

// DEBUG预处理变量
/**
 * assert的行为依赖于一个名为NDEBUG的预处理变量的状态。
 * 如果定义了NDEBUG，则assert什么也不做。默认状态下没有定义NDEBUG，此时assert将执行运行时检查。
 * 我们可以使用一个#define语句定义NDEBUG，从而关闭调试状态。
 * 
 * 如果NDEBUG未定义，将执行#ifndef和#endif之间的代码；如果定义了NDEBUG，这些代码将被忽略掉
 * 
 * 除了C++编译器定义的__func__之外，预处理器还定义了另外4个对于程序调试很有用的名字：
 * 1. __FILE__ 存放文件名的字符串字面值。
 * 2. __LINE__ 存放当前行号的整型字面值。
 * 3. __TIME__ 存放文件编译时间的字符串字面值。
 * 4. __DATE__ 存放文件编译日期的字符串字面值。
 */
void print(const int ia[],size_t size)
{
    #ifndef NDEBUG
        // __func__是编译器定义的一个局部静态变量，用于存放函数的名字
        cerr << __func__ << ":array size is " << size << endl;
    #endif
}

int main(int argc, char const *argv[])
{
    
    return 0;
}
